﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using MangaGrr.DomainModel;
using MangaGrr.MgrEventArgs;
using MinhUtils;

namespace MangaGrr.Logic
{
    class MangaChapterDownloader
    {
        private readonly MangaChapter _mangaChapter;

        public MangaChapter MangaChapter
        {
            get { return _mangaChapter; }
        }

        public MangaChapterDownloader(MangaChapter mangaChapter)
        {
            _mangaChapter = mangaChapter;
        }

        string firstPageURL = string.Empty;
        private string FirstPageURL
        {
            get
            {
                if (_mangaChapter.Manga.MangaSite.ChapterStartReadingPattern.Equals(string.Empty))
                {
                    return _mangaChapter.URL;
                }
                else
                {
                    if (firstPageURL.Equals(string.Empty))
                    {
                        string pageContent = NetUtil.TryDownloadContent(_mangaChapter.URL, 1000);
                        Match match = Regex.Match(pageContent, _mangaChapter.Manga.MangaSite.ChapterStartReadingPattern);
                        firstPageURL = StringUtil.PickURL(match.Value);
                    }

                    return firstPageURL;
                }
            }
        }

        private List<MangaPage> pageList = null;

        public event Action<object, TotalPageLoadedEventArgs> TotalPageLoaded;
        public event Action<object, NewPageLoadedEventArgs> NewPageLoaded;
        public event EventHandler LoadPageCompleted;

        protected void OnLoadPageCompleted(EventArgs e)
        {
            if (LoadPageCompleted != null)
                LoadPageCompleted.Invoke(this, e);
        }

        internal virtual ICollection<MangaPage> LoadPage()
        {
            pageList = new List<MangaPage>();

            //http://www.codersource.net/microsoft-net/c-advanced/html-screen-scraping-in-c.aspx
            string firstPageContent = LoadTotalPage();
            LoadPageFromSite(firstPageContent);

            OnLoadPageCompleted(new EventArgs());

            return pageList;
        }

        private void LoadPageFromSite(string pageContent)
        {
            Match match = null;

            //loop through pages and get the main image's URL
            for (int i = 0; i < _mangaChapter.TotalPage; i++)
            {
                match = Regex.Match(pageContent, _mangaChapter.Manga.MangaSite.PageImagePattern);

                MangaPage page = new MangaPage();
                page.Chapter = _mangaChapter;
                page.Number = i + 1;
                page.ImageURL = NetUtil.ToAbsoluteURL(StringUtil.PickURL(match.Value), _mangaChapter.URL);

                if (match.Value == string.Empty)
                    throw new Exception(string.Format("PageImagePattern is incorrect for MS{0}/MG{1}/CH{2}/PG{3}", _mangaChapter.Manga.MangaSite.Name, _mangaChapter.Manga.URL, _mangaChapter.URL, page.Number));

                NewPageLoadedEventArgs e = new NewPageLoadedEventArgs();
                e.NewPage = page;

                OnNewPageLoaded(e);

                pageList.Add(page);

                if (i == _mangaChapter.TotalPage - 1) //last page
                {
                    break;
                }
                else
                {
                    //get next page content
                    match = Regex.Match(pageContent, _mangaChapter.Manga.MangaSite.PageNextPagePattern);
                    string nextPageURL = StringUtil.PickURL(match.Value);

                    if (nextPageURL.ToLower().StartsWith("http") == false) //is a relative URL
                        nextPageURL = NetUtil.ToAbsoluteURL(nextPageURL, _mangaChapter.URL);

                    if (nextPageURL.Equals(_mangaChapter.URL) == false)
                        pageContent = NetUtil.TryDownloadContent(nextPageURL, 1000);
                    else
                        break;
                }
            }
        }

        protected void OnNewPageLoaded(NewPageLoadedEventArgs e)
        {
            if (NewPageLoaded != null)
            {
                NewPageLoaded.Invoke(this, e);
            }
        }

        /// <summary>
        /// Load total page of current chapter, return first page content for reusing.
        /// </summary>
        private string LoadTotalPage()
        {
            string firstPageContent = NetUtil.TryDownloadContent(this.FirstPageURL, 1000);

            //get the total number of pages
            Match match = Regex.Match(firstPageContent, _mangaChapter.Manga.MangaSite.ChapterTotalPagePattern);

            if (match.Value == string.Empty)
                throw new Exception(string.Format("ChapterTotalPagePattern is incorrect for MS{0}/MG{1}/CH{2}}", _mangaChapter.Manga.MangaSite.Name, _mangaChapter.Manga.URL, _mangaChapter.URL));

            _mangaChapter.TotalPage = StringUtil.PickInteger(match.Value);

            TotalPageLoadedEventArgs e = new TotalPageLoadedEventArgs();
            e.MangaChapter = _mangaChapter;
            e.TotalPage = _mangaChapter.TotalPage;

            OnTotalPageLoaded(e);

            return firstPageContent;
        }

        protected void OnTotalPageLoaded(TotalPageLoadedEventArgs e)
        {
            if (TotalPageLoaded != null)
            {
                TotalPageLoaded.Invoke(this, e);
            }
        }
    }
}
